#ifndef _IMAGEBIND_INFERENCE_H
#define _IMAGEBIND_INFERENCE_H
#include <string>
#include <unordered_set>
#include "cuda_runtime_api.h"
#include "logging.h"
#include "opencv2/opencv.hpp"
#include "NvInfer.h"
#include "yolov3_gpu_detector.h"
using namespace nvinfer1;


class imagebindInfer{
public:
    imagebindInfer();
    ~imagebindInfer();
    bool Initialize(const std::string& modelpath);
    void setParams(float aConfidenceThres,                           // Confidence threshold
                    std::unordered_set<std::string> aTargetClassname, // Classes need to be detected
                    std::string aModelFilePath,                       // Model file path
                    size_t aWidth,                                    // Block width to DNN
                    size_t aHeight);
    bool inference(cv::Mat &visible_pFrame,
                    yoloV3GPUDetector &yolo,
                    std::vector<cv::Rect2d> &pRoi,
                    std::vector<std::string> &pName,
                    std::vector<float> &pConf
                          );

    bool initModelConfig(const std::string modelconfigpath);

    bool initModelRunCon(const std::string modelRunconfigpath);

    bool initEngine(const std::string enginePath);

    std::vector<float> means;
    std::vector<float> stds;
    std::unordered_set<std::string> target_names;
    std::unordered_set<std::string> imagebind_class_names;
    float temperature = 10;
    float cof_threshold = 0.5;
    std::string model_path;
    std::string text_emdeding_path;
    bool first_init =false;
    int pattern = 1;
    int imagebind_detect_order = 0;

private:
    IExecutionContext* context;
    IRuntime* runtime;
    ICudaEngine* engine;

    std::vector<float> _embeddings;
    std::vector<std::map<std::string ,std::vector<float>>> _known_embeddings;
    std::vector<std::string> cls_names;
    size_t _clip_Width=224, _clip_Height=224;
    size_t _embedding_size;
};
bool image_preprocess(const cv::Mat &src_image, int width, int height, std::vector<float> &input_vectors,std::vector<float> &means, std::vector<float> &stds);
bool cv2vec(const cv::Mat src_image, std::vector<float> &input_vectors);
bool load_pre_text_embeddings(std::string path, std::vector<std::map<std::string ,std::vector<float>>> &known_embeddings, std::vector<std::string> cls_names);
std::vector<float> softmax(std::vector<float> &conf, float temperature=100);

#define CHECK(status) \
    do\
    {\
        auto ret = (status);\
        if (ret != 0)\
        {\
            std::cerr << "Cuda failure: " << ret << std::endl;\
            abort();\
        }\
    } while (0)

#endif